/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package za.co.pas.business.model;

import java.util.Collections;
import java.util.LinkedList;
import za.co.pas.business.abstracts.AbstractDataModel;
import java.util.List;
import javax.persistence.EntityExistsException;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;
import org.apache.log4j.Logger;
import za.co.pas.business.data.*;
import za.co.pas.business.message.StatusMessage;
import za.co.pas.business.message.StatusMessageObject;

/**
 *
 * @author alabuschagne
 */
//@NamedQuery(name="getUserLoginDetails",query="SELECT c FROM Customer c WHERE c.name LIKE :custName")
public class UserDataModel extends AbstractDataModel
{
    private List<UserGroups> userGroups = new LinkedList<UserGroups>();
    private List<UserType> userTypes = new LinkedList<UserType>();
    private static Logger logger = Logger.getLogger(UserDataModel.class);

    
    public void addUserLoginDetails(UserLoginDetails userLoginDetails) throws
                                                    EntityExistsException
    {
        super.persistGenericObject(userLoginDetails);
    }

    /**
     * Get the user using the user's login details
     * @param username
     * @param password
     * @return The user's details
     */
    public UserLoginDetails getUserLoginDetails(String username, String password)
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting user details for " + username, StatusMessageObject.SMO_TYPE_READ));
            String MD5Password = doMD5(password);
            Query q = em.createQuery("SELECT c FROM UserLoginDetails c WHERE c.userName LIKE :uName AND c.password LIKE :pWord").setParameter("uName", username).setParameter("pWord", MD5Password);
            //.setMaxResults(10);
            setConnectionOk(true);
            return (UserLoginDetails) q.getSingleResult();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "Did not get any results for user using " + username, StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public UserType getUserType(String name)
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting user type for " + name, StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM UserType c WHERE c.name LIKE :name").setParameter("name", name);
            //.setMaxResults(10);
            setConnectionOk(true);
            return (UserType) q.getSingleResult();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "Did not get any results for user type using " + name, StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    private List<UserType> getUserTypesDB()
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting all user types", StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM UserType c");
            setConnectionOk(true);
            return q.getResultList();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "Did not get any results for user types", StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public boolean checkDB()
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting all user details", StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM UserLoginDetails c");
            //.setMaxResults(10);
            setConnectionOk(true);
            List<UserLoginDetails> list = q.getResultList();
            if(list.isEmpty())
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "Did not get any results for users", StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
            return false;
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return false;
    }

    public UserGroups getUserGroup(String name)
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting user group for " + name, StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM UserGroups c WHERE c.name LIKE :name").setParameter("name", name);
            //.setMaxResults(10);
            setConnectionOk(true);
            return (UserGroups) q.getSingleResult();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "Did not get any results for user type group " + name, StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public List<UserGroups> getUserGroups(boolean force)
    {
        if((userGroups == null) || (userGroups.isEmpty()) || force)
        {
            userGroups = getUserGroupsDB();
            Collections.sort((List)userGroups);
        }
        return userGroups;
    }

    private List<UserGroups> getUserGroupsDB()
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting all user groups", StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM UserGroups c");
            setConnectionOk(true);
            return q.getResultList();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "Did not get any results for user groups", StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public List<UserType> getUserTypes(boolean force)
    {
        if((userTypes == null) || (userTypes.isEmpty()) || force)
        {
            userTypes = getUserTypesDB();
            Collections.sort((List)userTypes);
        }
        return userTypes;
    }

    public void addUserGroups(UserGroups ug)
    {
        if(userGroups == null)
        {
             userGroups = getUserGroupsDB();
        }
        if(userGroups == null)
        {
            userGroups = new LinkedList<UserGroups>();
        }
        userGroups.add(ug);
    }
}
